import cgi
import os
import urllib
import logging
import model
import rating




from base import BaseRequestHandler
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from google.appengine.api import memcache
from datetime import datetime, date, time, timedelta

# Set the debug level
_DEBUG = True


class MainRequestHandler(BaseRequestHandler):
  def get(self):
    self.generate_right_page("0")


class RoomRequestHandler(BaseRequestHandler):

  def get(self):
    logging.debug("Room request")
    #params = self.extract_params(self.request.url)
    self.crumble_response.reset()
    self.init_crumble_user()
    table_number = self.request.get('table')
    if (self.crumble_user != None and table_number != None and table_number != ""):
        logging.debug("Request for table" + table_number)
        if (int(table_number) and int(table_number) > 0) :
          template_values = {'table':model.get_updated_table(table_number),
                             'leave_table_url':"/room"}
          self.generate('crumble2.html', template_values)
          return
    if table_number == None:
      table_number = "0"
    self.generate_right_page(table_number)

class NewTableRequestHandler(BaseRequestHandler):

  def get(self):
    self.crumble_response.reset()
    self.init_crumble_user()
    game = model.Game()
    game.put()
    table_number = game.table_number
    self.generate_right_page(table_number);

class GameRequestHandler(BaseRequestHandler):
  def get(self):
    self.crumble_response.reset()
    self.init_crumble_user()
    table_number = self.request.get('table')
    # game start : move_id = 1
    move_id = int(self.request.get('moveId'))
    game = model.get_game(table_number)
    if (game != None):
      logging.debug("Game started")
      for i in range(1, len(game.moves)):
        logging.debug(game.moves[i])

    logging.debug("game : " + str(game) + " requesting moves starting with " + str(move_id))
    if (game != None and len(game.moves) > move_id):
      for i in range(move_id, len(game.moves)):
        self.crumble_response.moves[str(i)] = game.moves[i]
      self.crumble_response.lastMoveId = len(game.moves)-1
      self.crumble_response.status = "ok"
      #self.response.out.write(game.moves[int(move_id)])

    #elif (game != None and len(game.moves) < move_id):

      #self.crumble_response.set_error("ERROR: Requesting invalid move id: " + str(move_id) + " Expecting at most " + str(len(game.moves)))
    self.write_response()
  def post(self):
    self.crumble_response.reset()
    self.init_crumble_user()
    table_number = self.request.get('table')
    move_id = self.request.get('moveId')
    winner = self.request.get('winner')
    game = model.get_game(table_number)
    logging.debug("table = " + table_number)
    user = users.get_current_user()
    if (game == None):
        self.crumble_response.set_error("ERROR: Game was not started")
    elif (user != game.player_white and user != game.player_black):
        self.crumble_response.set_error("ERROR: Can not make a move - you are not a player")
    else:
      logging.debug("+++" + str(int(move_id) - game.last_move_id))
      if (len(game.moves) != int(move_id)):
        self.crumble_response.set_error("ERROR: Submitted move is " + move_id + ". Expecting " + str(len(game.moves)))
      elif (int(move_id) == game.last_move_id + 1):
        move = self.request.get('content')
        logging.debug("Received move " + move_id + "\n" + move)
        game.moves.append(move)
        game.last_move_id = int(move_id)
        logging.debug("Storing last_move_id = " + str(game.last_move_id))
        if (winner == "White" or winner == "Black"):
          self.complete_game(game, winner);
        game.put()
      else:
        self.crumble_response.set_error("ERROR: expecting move " + str(game.last_move_id + 1) + ", but got " + move_id)

    self.write_response()


  def complete_game(self, game, win_color):
    logging.debug("Completing game. " + win_color + " won")
    white = model.get_crumble_user(game.player_white)
    black = model.get_crumble_user(game.player_black)
    if (win_color == "White"):
        game.winner = model.Color.White
        winner = white
        loser = black
    else:
        game.winner = model.Color.Black
        winner = black
        loser = white
    rating.update_rating(winner, loser);

class NewGameRequestHandler(BaseRequestHandler):
  def get(self):
    self.crumble_response.reset()
    self.init_crumble_user();
    table_number = self.request.get('table')
    color = self.request.get('color')
    game = model.get_game(table_number)
    # TODO: Fix this
    user = users.get_current_user()

    if (game == None):
      logging.error("No game found for table " + table_number + "!!!")
      self.crumble_response.set_error("ERROR: Game was not found for table " + table_number)
    else:
      if (game.player_white != None and game.player_black != None):
        self.crumble_response.lastMoveId = len(game.moves)-1
        self.crumble_response.whitePlayer = game.player_white.email();
        self.crumble_response.blackPlayer = game.player_black.email();

      if (game.player_white == None and color == "White" ):
        logging.debug("Found white player for table " + table_number)
        game.player_white = user
        if (game.player_black == user):
            game.player_black = None
        logging.debug("Found white player for table " + table_number)
      if (game.player_black == None and color == "Black" ):
        game.player_black = user
        if (game.player_white == user):
            game.player_white = None
        logging.debug("Found black player for table " + table_number)

      if (game.player_white == user):
        self.crumble_response.status = "white"
      elif (game.player_black == user):
        self.crumble_response.status = "black"
      else:
        self.crumble_response.status = "watch"

      if (game.player_white == None):
        self.crumble_response.status = "wait_white"
      elif (game.player_black == None):
        self.crumble_response.status = "wait_black"
      game.put()

    logging.debug("New game return: " + self.crumble_response.status)
    self.write_response()

class PlayerAliveRequestHandler(GameRequestHandler):
  def get(self):
    self.crumble_response.reset()
    self.init_crumble_user()
    if (self.crumble_user != None):
      table_number = self.request.get('table')
      is_active = self.request.get('is_active')
      self.crumble_user.last_ping = datetime.now()

      users = self.get_users(table_number)
      if (users == None):
        users = []
      found = False
      for cu in users:
        if cu.email == self.crumble_user.email:
          cu.active = is_active
          found = True
          logging.debug("found user, not adding to the list")
          break
      if not found:
        self.crumble_user.active = is_active
        self.crumble_user.table_number = str(table_number)
        users.append(self.crumble_user)
        self.set_users(table_number, users)
      if table_number == "0":
        tables = self.get_tables()
        logging.debug("Number of tables with active users: " + str(len(tables)))
        for t, us in tables.items():
          if not t == "0":
            logging.debug("INITIAL NUMBER OF USERS: " + str(len(us)))
            onlyActiveUsers = self.get_users(t);
            logging.debug("ONLY ACTIVE NUMBER OF USERS: " + str(len(onlyActiveUsers)))
            if (len(onlyActiveUsers) > 0):
              users.extend(onlyActiveUsers) #trim from the old users
      self.crumble_response.set_users(users)
    self.write_response()

  def get_users(self, table_number, useCache=True):
    alreadyProcessing = False
    users = self.get_tables().get(str(table_number))
    lastUpdateTime = memcache.get("lastUpdateTime" + table_number)
    now = datetime.now()
    if (not alreadyProcessing and (lastUpdateTime == None or now - lastUpdateTime > timedelta(minutes = 8))):
      alreadyProcessing = True
      memcache.set("lastUpdateTime" + table_number, now)
      modified = False
      if (users != None):
        updatedUsers = []
        for cu in users:
          if now - cu.last_ping < timedelta(minutes = 10):
            updatedUsers.append(cu)
          else:
            modified = True
        logging.debug("retrieving users from memcache")
        users = updatedUsers
        if (users != None):
          logging.debug("users : " + str(len(users)) + " for table " + table_number)
      if modified:
        self.set_users(table_number, users)
    return users

  def set_users(self, table_number, users, useCache=True):
    logging.debug("setting users to memcache: users : " + str(len(users)) + " for table " + table_number)
    tables = memcache.get("tables")
    tables[table_number] = users
    if not memcache.set("tables", tables):
      logging.error("Memcache set failed:")

  def get_tables(self):
    tables = memcache.get("tables")
    if (tables == None):
      tables = {}
      if not memcache.set("tables", tables):
        logging.error("Memcache set failed:")
    return tables

class LeaveTableRequestHandler(GameRequestHandler):
  def get(self):
    self.crumble_response.reset()
    self.init_crumble_user()
    table_number = self.request.get('table')
    logging.debug(self.crumble_user.email + " is leaving table " + table_number)

    user = users.get_current_user()

    greeting = model.Greeting()
    greeting.table_number = table_number

    if users.get_current_user():
      greeting.author = users.get_current_user()

    greeting.content = "(automated) I left the table"
    greeting.put()

    #self.generate_right_page("0")


class ChatsRequestHandler(BaseRequestHandler):
  def get(self):
      table_number = self.request.get('table')
      self.getChats(table_number)

  def post(self):
      table_number = self.request.get('table')
      self.postChats(table_number)

  def renderChats(self, table_number):
    greetings = model.get_greetings(table_number)

    template_values = {
      'greetings': greetings,
    }
    return self.generate('chats.html', template_values)

  def getChats(self, table_number, useCache=True):
    if useCache is False:
      greetings = self.renderChats(table_number)
      if not memcache.set("chat" + table_number, greetings, 10):
        logging.error("Memcache set failed:")
      return greetings

    greetings = memcache.get("chats" + table_number)
    if greetings is not None:
      return greetings
    else:
      greetings = self.renderChats(table_number)
      if not memcache.set("chat" + table_number, greetings, 10):
        logging.error("Memcache set failed:")
      return greetings


  def postChats(self, table_number):
    self.init_crumble_user()

    greeting = model.Greeting()
    if (table_number):
        greeting.table_number = table_number

    if users.get_current_user():
      greeting.author = users.get_current_user()

    greeting.content = self.request.get('content')
    logging.debug("CHAT" + greeting.content)
    greeting.put()

    self.getChats(table_number, False)


application = webapp.WSGIApplication(
                                     [('/', MainRequestHandler),
                                      ('/room', RoomRequestHandler),
                                      ('/game', GameRequestHandler),
                                      ('/newgame', NewGameRequestHandler),
                                      ('/leavetable', LeaveTableRequestHandler),
                                      ('/getchats', ChatsRequestHandler),
                                      ('/updateUserStatus', PlayerAliveRequestHandler),
                                      ('/newtable', NewTableRequestHandler),
                                     ],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()